home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-03-19 | 13.2 KB | 297 lines | [TEXT/MPS ] |
- #########################################################################
- #########################################################################
- ## Copyright © Apple Computer, Inc. 1992-1997
- ## All rights reserved
- #########################################################################
- #########################################################################
- #
- # Library: Message.lib
- #
- # Version: 2.1.4
- #
- # Description:
- # Contains helpful tasks for actors to communicate between themselves
- # using the VU message passing mechanism. They are essentially the four
- # messaging primitives with some error checking and reporting added on.
- # For a complete description of the messaging feature, see the Virtual
- # User Language Reference. Here are some tips:
- #
- # Actors do not exist unless they are running a script. The statement:
- # match[actor t:$allActors];
- # puts a list of actors into allActors, but only those which are
- # currently running scripts (the scripts can be the same or different).
- # For messaging, the term "actor" refers to an actor running a script.
- #
- # A message consists of a string. As long as you have opened a session
- # with another actor, you can send a list of messages, which is relatively
- # fast to complete from your actor's point of view, because the whole list
- # is accepted as one parameter by the send() primitive. However, receiving
- # a list is slow, since the receive() primitive returns just one message at
- # a time, even if the sender sent a list. You must loop until you receive all
- # expected messages, which implies you must know in advance how many were sent.
- #
- # Actors must agree in advance (by design is easier than by negotiation) on
- # the kinds of messages possible and their length. This way the first
- # message received tells what kind of message, and by its definition implies
- # how many more will follow, so you know when to terminate the loop.
- # One of the most common causes of failure when using messages is getting
- # de-synchronized, where one actor is re-sending after the other's
- # response has been sent, but has not yet reached the first actor.
- #
- # Message strings take several seconds each (at least) to get to the
- # other actor. This is an artifact of their implementation. Currently
- # there are no plans to improve the performance of messages, so you
- # should not use them extensively. Their main use in the LaunchQuit
- # engine is to allow registration of applications which perform
- # serial number conflict checking over the network, so that if one
- # actor has launched the application, others are locked out until the
- # current actor un-registers. This is rare enough that the substantial
- # additional time to complete the test case (more than a minute if no other
- # applications have registered first) does not substantially alter the
- # average time per test case. See the script called Arbitrator.vu.
- #
- # Messaging can take a really long time if all actors send and receive
- # to and from the same actor (e.g. the Arbitrator) which must service each
- # actor in round-robin fashion. You will need to use large timeout
- # values to prevent unexpected failures when receiving. Again, sending takes
- # little time because it does not wait for a response from the other actor.
- # It is almost as if messages are "posted" on a bulletin board, then each
- # actor looks at the board everytime its thread becomes active, and grabs
- # any messages for itself. The posting takes almost no time, but since only
- # one message is received for each thread switch, receiving takes longer.
- #
- # Contains:
- # connect_to()
- # disconnect_from()
- # send_list()
- # receive_list()
- #
- # History:
- # Date: By: Changes:
- # 12/15/92 SBR Created
- # 02/01/94 SBR Added comments
- # 06/01/96 SBR/MSO Updated copyright header
- # 01/21/97 SBR Updated copyright header.
- #
- #########################################################################
- #########################################################################
- Libraries
- "Clouseau.lib",
- "Report.lib";
-
-
- #########################################################################
- # task connect_to( toWhom, maxTime, v_level )
- #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
- # Description: Use this to open a session with another actor. Once the other actor
- # calls connect_to() with your actor's name, then both can send messages
- # to each other.
- # Parameters: toWhom: string name of the running actor to open a session with
- # maxTime: integer maximum number of seconds to wait for the other
- # actor to open a session with your actor; make this fairly
- # large if multiple actors are running
- # v_level: verbosity level for debugging
- # Returns: true: The session opened within the allotted time.
- # false: The session did not open within the allotted time. This
- # Note: The session may still open later since the other actor
- # may keep trying. However, never try messaging unless
- # this routine returns true.
- # Examples: if not connect_to('Arbitrator',60)
- # println "Could not connect to the Arbitrator, is it running?";
- # Assumptions: None
- #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
- # History:
- # 12/15/92 SBR Created
- # 02/01/94 SBR Added ! to make the actor match exact
- # 02/02/94 SBR Changed timer to use real time
- # 08/06/94 SBR Changed timer to use timed_out, removed RIncomplete v_level
- #########################################################################
- task connect_to( toWhom := '', maxTime := 10, v_level := 3 )
- begin
- RStatus("connect_to: Open session with '{toWhom}' within {maxTime} seconds", v_level);
-
- end_time := get_end_time(maxTime);
- status := '';
- outOfTime := false;
-
- while (status <> 'open') and (not outOfTime) #always try once
- begin
- if not match[actor t:toWhom]!
- return RIncomplete("connect_to: The actor '{toWhom}' is not present");
- status := openSession([actor t:toWhom]);
-
- theError := ScriptError();
- if theError
- return RIncomplete("connect_to: connect to '{toWhom}' failed " +
- "(status: {status}, ScriptError: {theError}).");
-
- RStatus("connect_to: Status is {status} after this attempt.", v_level);
- wait(1);
-
- outOfTime := timed_out(end_time);
- end;
- if status = 'open'
- return RStatus("connect_to: connect to '{toWhom}' succeeded.", v_level);
- else
- return RIncomplete("connect_to: connect to '{toWhom}' failed ({status}).");
- end;
-
- #########################################################################
- # task disconnect_from( fromWhom, v_level )
- #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
- # Description: Use this to close a session with another actor which was already open.
- # Note: This does not require the other actor to respond or even to
- # disconnect, so there is no timeout value. The only way it can
- # fail is if the session is not open at this end. It may already
- # be closed at the other end.
- # Parameters: fromWhom: string name of the connected actor to disconnect from
- # v_level: verbosity level for debugging
- # Returns: true: The session was open and now is closed.
- # false: The session was not open at this end, but it is closed now.
- # Examples: if not disconnect_from('Arbitrator')
- # println "Could not disconnect to the Arbitrator, was it connected?";
- # Assumptions: Already connected at other end.
- #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
- # History:
- # 12/15/92 SBR Created
- # 02/01/94 SBR Added ! to make the actor match exact
- # 08/06/94 SBR Added ScriptError() check, removed RIncomplete v_level
- #########################################################################
- task disconnect_from( fromWhom := '', v_level := 3 )
- begin
- RStatus("disconnect_from: Attempting to close session with '{fromWhom}'",v_level);
-
- wait(1);
-
- if not match [actor t:fromWhom]!
- return RIncomplete("disconnect_from: The actor '{fromWhom}' is not present");
- status := closeSession([actor t:fromWhom]);
-
- theError := ScriptError();
- if theError
- return RIncomplete("disconnect_from: disconnect from '{fromWhom}' failed " +
- "(status: {status}, ScriptError: {theError}).");
-
- if status = 'done'
- return RStatus("disconnect_from: disconnect from '{fromWhom}' succeeded.", v_level);
- else
- return RIncomplete("disconnect_from: disconnect from '{fromWhom}' failed " +
- "(status: {status}).");
- end;
-
-
- #########################################################################
- # task send_list( toWhom, myList := {}, v_level )
- #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
- # Description: Use this to send messages to another actor you have already opened
- # a session with that actor using connect_to(). The other actor must
- # know how many items you are sending.
- # Note: Generally, the only way for this to fail is if the session
- # is not already open or if the actor is no longer running a
- # script. The real work goes on at the receiver.
- # Parameters: toWhom: string name of the connected actor you want to send to
- # myList: list of regular expressions or integers, which VU
- # converts to a list of strings before sending.
- # v_level: verbosity level for debugging
- # Returns: true: The messages were sent with no errors.
- # false: There was an error sending the messages.
- # Examples: if not send_list('Arbitrator', {'useApplication','Canvas 3.0.6@'})
- # println "Could not send to the Arbitrator, is it still running?";
- # Assumptions: Session is already open with other actor
- #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
- # History:
- # 12/15/92 SBR Created
- # 08/06/94 SBR Removed RIncomplete v_level
- #########################################################################
- task send_list( toWhom := '', myList := {}, v_level := 3 )
- begin
- listLength := card myList;
- sendSuccess := send([actor t:toWhom], myList);
-
- theError := ScriptError();
- if theError
- RIncomplete("send_list: Error {theError} sending '{toWhom}' " +
- "the message:{myList} (status: {sendSuccess}, ScriptError: {theError}).");
- if sendSuccess
- return RStatus("send_list: Sent '{toWhom}' a message with {listLength} items.", v_level);
- else
- return RIncomplete("send_list: Failed to send '{toWhom}' the message:{myList}.");
- end;
-
-
- #########################################################################
- # task receive_list( fromWhom, msgNum, maxTime, v_level )
- #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
- # Description: Use this to receive messages from another actor. The receive()
- # primitive may return a null string in between consecutive messages
- # sent from another actor, even if they were sent in the same list.
- # For this reason, this task loops over a specified period of time,
- # until the expected number of non-null strings are returned. This
- # means you can not send a null string on purpose.
- # Parameters: fromWhom: string: name of the connected actor to receive from
- # msgNum: integer: expected number of messages to receive within the
- # amount of time allowed
- # maxTime: integer: maximum total number of seconds to
- # receive ALL the messages (not each message); make this
- # fairly large if multiple actors are running
- # v_level: integer: verbosity level for debugging
- # Returns: true: Within maxTime seconds, msgNum strings were received with
- # no errors.
- # false: There was an error, or msgNum messages were not received
- # within maxTime seconds.
- # Examples: myReceivedMsgs := receive_list('Arbitrator',3,180);
- # if not myReceivedMsgs
- # println "Could not receive 3 messages from the Arbitrator!";
- # Assumptions: Session is already open with other actor. It is not required that
- # the other actor sends anything, but the caller of this routine
- # must decide when to give up.
- #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
- # History:
- # 12/15/92 SBR Created
- # 02/02/94 SBR Added return for ScriptError case, changed timer to "manual"
- # 08/06/94 SBR Changed timer to use timed_out, removed RIncomplete v_level
- #########################################################################
- task receive_list( fromWhom := '', msgNum := 1, maxTime := 10, v_level := 3 )
- begin
- msgsRcd := {};
- rTries := 0;
- allDone := false;
- outOfTime := false;
- end_time := get_end_time(maxTime);
-
- while not (outOfTime or allDone) #always try once
- begin
- rTries := rTries + 1;
- msgReceived := receive([actor t:fromWhom]);
-
- theError := ScriptError();
- if theError
- begin
- returnString := "receive_list: Error {theError} receiving {msgNum}" +
- " items from '{fromWhom}' at item #{rTries}'." +
- " Partial msg: {msgsRcd}.";
- return RIncomplete(returnString);
- end;
-
- if msgReceived
- begin
- RStatus("receive_list: Received message '{msgReceived}' on attempt #{rTries}.", v_level);
- msgsRcd := msgsRcd + {msgReceived};
- if card msgsRcd = msgNum
- return msgsRcd;
- end;
- else
- RStatus("receive_list: Received nothing from '{fromWhom}' on attempt #{rTries}.", v_level);
-
- if timed_out(end_time)
- begin
- outOfTime := true;
- returnString := "receive_list: Timed out receiving from '{fromWhom}'";
- return RIncomplete("{returnString}, attempt #{rTries}. Partial msg: {msgsRcd}.");
- end;
- wait(1);
- end;
- end;
-
-
-